package text.adventure.persistance;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

import text.adventure.data.GameObject;
import text.adventure.data.GenericResponseObject;
import text.adventure.data.ImageFinderObject;
import text.adventure.data.Message;
import text.adventure.data.Reaction;
import text.adventure.data.RoomObject;
import text.adventure.data.TextCommand;
import android.content.Context;


public class XMLGameFileParser extends DefaultHandler implements GameFileParser  {

	String[] pathCollection;
	
	StringBuffer buff = null;
    boolean buffering = false; 
    
    String current = "";
    GameObject currentObject;
    TextCommand currentInCommand;
    TextCommand currentOutCommand;
    Reaction currentReaction;
    List<String> inObjects;
    List<String> outObjects;
    boolean inputOrOutput; //true in ; false out
    boolean inventory;
    
	public XMLGameFileParser(String[] pathCollection, Context context) {
		this.pathCollection = pathCollection;
		SAXParserFactory spf = SAXParserFactory.newInstance();
		try {
			SAXParser sp = spf.newSAXParser();
			XMLReader xr = sp.getXMLReader();
			xr.setContentHandler(this);
			for (String path : pathCollection) {
				xr.parse(new InputSource(context.getAssets().open(path)));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public GameObject getInvItem(String id) {
		return data.getGeneralObject(id);
	}

	@Override
	public List<GameObject> getInvItem(String[] id) {
		return data.getGeneralObjects(id);
	}

	@Override
	public List<GameObject> getGenerics() {
		return data.getGeneralObjects();
	}

	@Override
	public List<GameObject> getFromRoomId(int id) {
		return data.getFromRoomId(id);
	}
	
	  @Override
	    public void startElement(String namespaceURI, String localName, String qName, 
	            Attributes atts) throws SAXException {
	      if (localName.equals("Chapter")) {
	        	data.addChapter(Integer.parseInt(atts.getValue("id")));
	        } else if (localName.equals("Roomstructure")) {
	        	data.addRoom(Integer.parseInt(atts.getValue("id")));
	        } else if (localName.equals("General")) {
	        	inventory = true;
	        } else if (localName.equals("Room")) {
	        	currentObject = new RoomObject(atts.getValue("name"));
	        } else if (localName.equals("Object")) {
	        	currentObject = new GameObject(atts.getValue("name"));
	        } else if (localName.equals("GenericOutput")) {
	        	currentObject = new GenericResponseObject();
	        } else if (localName.equals("ImgFinder")) {
	        	currentObject = new ImageFinderObject();
	        } else if (localName.equals("Flags")) {
	        	addFlags(atts);
	        } else if (localName.equals("Inputcommand")) {
	        	inputOrOutput = true;
	        	currentInCommand = new TextCommand(false, atts.getValue("verb"));
	        	inObjects = new ArrayList<String>();
	        	}else if (localName.equals("Outputcommand")) {
		        	inputOrOutput = false;
		        	currentOutCommand = new TextCommand(false, atts.getValue("verb"));
		        	outObjects = new ArrayList<String>();
		        	currentReaction = new Reaction();
		        	if (atts.getValue("conditional") == "True") {
		        			currentReaction.setScripted(true);
		        		//TODO conditional
		        	} else {
		        		currentReaction.setScripted(false);
		        	}}
	        	else if (localName.equals("Object")) {
	        		buffering = true;
	        		buff = new StringBuffer("");
	        } else if (localName.equals("Output")) {
	        	buffering = true;
	        	buff = new StringBuffer("");
	        } else if (localName.equals("Script")) {
	        	//TODO Script
	        } 
	      
	    } 
	    
	    @Override
	    public void characters(char ch[], int start, int length) {
	        if(buffering) {
	            buff.append(ch, start, length);
	        }
	    } 
	    
	    @Override
	    public void endElement(String namespaceURI, String localName, String qName) 
	    throws SAXException {
	    	buffering = false; 
	    	if (localName.equals("Object")) {
	            
	            if (inputOrOutput) {
	            	inObjects.add(buff.toString());
	            } else {
	            	outObjects.add(buff.toString());
	            }
	            
	        } else if (localName.equals("Output")) {
        		currentReaction.addOutput(new Message(buff.toString()));
	        } else if (localName.equals("Inputcommand")) {
	     		currentInCommand.setObjects(inObjects.toArray(new String[inObjects.size()]));
	     		currentObject.addBehavior(currentInCommand, currentReaction);
	        } else if (localName.equals("Outputcommand")) {
	     		currentOutCommand.setObjects(outObjects.toArray(new String[outObjects.size()]));
	     		currentReaction.addcommand(currentOutCommand);
	        } else if (localName.equals("Room") || (localName.equals("Object") && !inventory)) {
	     		data.addToCurrentRoom(currentObject);
	        } else if ((localName.equals("Object") && inventory) ||
	        		localName.equals("GenericOutput") || localName.equals("ImgFinder")) {
	     		data.addGeneralObject(currentObject);
	        }
	    }
	
	    
	    private void addFlags(Attributes atts) {
	    	Map<String, Boolean > flags = new HashMap<String, Boolean>();
	    	for (int i = 0; i < atts.getLength(); i++) {
	    		boolean val = false;
	    		if (atts.getValue(i) == "True") {
	    			val = true;
	    		}
	    		flags.put(atts.getQName(i), val);
	    	}
	    	currentObject.setFlags(flags);
	    }

}
